using Engine;
using Engine.Camera;
using Engine.FileFormats3D;
using Engine.FileFormats3D.WR2TerrainLoader.Misc;
using Engine.Graphics;
using Scenario_Editor.AddinManager;
using SharpDX;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using WorldRacing2.Material;
using WorldRacing2.Scenario.WR2TerrainLoader;
using WorldRacing2.Scenario.WR2TerrainLoader.QadFile;

namespace WorldRacing2.Scenario
{
    public class Wr2Scenario : IRenderableObject, IDisposable, ISceneryExtractor
    {
        #region Private Fields

        private Engine.Engine engine;
        private IDXFile idxFile;
        private MaterialManager materialManager;
        private Meshobject[] meshBlocks;
        private Mesh3dData[] meshes;
        private QADFile qadFile;
        private SceneManagement sceneManagement;
        private ShaderManager shaderManager;
        private VTXFile vtxFile;

        #endregion Private Fields

        #region Public Constructors

        public Wr2Scenario(string scenerieFolder, Engine.Engine engine, ShaderManager shaderManager, Camera camera, float viewDistance)
            : this(scenerieFolder)
        {
            this.engine = engine;
            this.shaderManager = shaderManager;

            //Create the MaterialManager.
            List<string> texturePaths = new List<string>();
            foreach (var textureName in this.qadFile.TextureNames)
            {
                texturePaths.Add(scenerieFolder + "\\V1\\Textures\\" + textureName.ToString() + ".ptx");
            }

            //Add the Wr2 Surfaces to the Material Manager
            this.materialManager = new MaterialManager(engine, texturePaths);
            int materialID = 1;
            foreach (var surface in this.qadFile.Surfaces)
            {
                Engine.Graphics.Material material = new Engine.Graphics.Material(surface.ToMaterial(this.materialManager));
                material.MaterialName = "Material " + materialID.ToString();
                materialID++;
                this.materialManager.AddNewMaterial(material, false);
            }
            CreateMeshes(this.vtxFile, this.qadFile, this.idxFile);

            this.sceneManagement = new SceneManagement(this.materialManager, shaderManager, camera, viewDistance);

            CreateRenderMeshObjects();
        }

        #endregion Public Constructors

        #region Private Constructors

        private Wr2Scenario(int sizeX, int sizeY)
        {
            this.vtxFile = new VTXFile();
            this.idxFile = new IDXFile();
            this.qadFile = new QADFile(sizeX, sizeY);
            this.meshBlocks = new Meshobject[sizeX * sizeY];
        }

        private Wr2Scenario(string scenerieFolder)
        {
            //WR2ScenarioDebugPanel debugPanel = new WR2ScenarioDebugPanel();
            //debugPanel.Show();

            string fileName = scenerieFolder + "\\V1\\" + GetSceneryName(scenerieFolder);
            //Loading the vtx-File. All vertices are stored in here.
            this.vtxFile = VTXFile.FromFile(fileName + ".vtx");

            //Loading qad-File. All Objects, Sounds, Materials ... are stored in here.
            this.qadFile = QADFile.FromFile(fileName + ".qad");

            //Loading the idx-File. All Indices from all chunks are stored in this file.
            this.idxFile = IDXFile.FromFile(fileName + ".idx");

            this.meshBlocks = new Meshobject[this.qadFile.CellsX * this.qadFile.CellsY];
            this.meshes = new Mesh3dData[this.qadFile.CellsX * this.qadFile.CellsY];
        }

        private Wr2Scenario()
        {
            this.vtxFile = new VTXFile();
            this.qadFile = new QADFile();
            this.idxFile = new IDXFile();
        }

        #endregion Private Constructors

        #region Private Destructors

        ~Wr2Scenario()
        {
            Dispose();
        }

        #endregion Private Destructors

        #region Public Delegates

        public delegate void ExportStatus(object sender, EventArgs e);

        #endregion Public Delegates

        #region Public Events

        public static event ExportStatus exportStatus;

        #endregion Public Events

        #region Public Properties

        public IDXFile IdxFile
        {
            get { return this.idxFile; }
            set { this.idxFile = value; }
        }

        public MaterialManager MaterialManager
        {
            get { return this.materialManager; }
            set { this.materialManager = value; }
        }

        public Meshobject[] MeshBlocks
        {
            get { return this.meshBlocks; }
            set { this.meshBlocks = value; }
        }

        public Mesh3dData[] Meshes
        {
            get { return this.meshes; }
            set { this.meshes = value; }
        }

        public QADFile QadFile
        {
            get { return this.qadFile; }
            set { this.qadFile = value; }
        }

        public VTXFile VtxFile
        {
            get { return this.vtxFile; }
            set { this.vtxFile = value; }
        }

        #endregion Public Properties

        #region Public Methods

        public static Wr2Scenario CreateNewScenery(string sceneryFolder, List<Engine.Physic.Ground> grounds,
            Dictionary<string, TexturePropertie> textureProperties, Mesh3dData[] meshes, int height, int width)
        {
            Wr2Scenario wr2Scenario = new Wr2Scenario(width, height);
            SendExportStatus(string.Format("Created new Scenerie: {0}x{1}", height, width));
            CreateSceneryBlocks(meshes, height, width, wr2Scenario);

            wr2Scenario.QadFile.SetGrounds(grounds);
            wr2Scenario.qadFile.UpdateGrounds(textureProperties);

            SendExportStatus(string.Format("\n\nPolys: {0}\n", wr2Scenario.qadFile.NumberOfPolygons));
            SendExportStatus(string.Format("\n\nVertices: {0}\n", wr2Scenario.vtxFile.GetNumberOfVertices()));
            SendExportStatus(string.Format("Scenerie saved: {0}", sceneryFolder));

            return wr2Scenario;
        }

        public static Wr2Scenario UpdateScenario(string sceneryFolder, List<Engine.Physic.Ground> grounds,
            Dictionary<string, TexturePropertie> textureProperties, Mesh3dData[] meshes, int height, int width,
            Engine.DynamicObjectManager.SceneryObjectManager objects)
        {
            Wr2Scenario wr2Scenario = new Wr2Scenario();
            wr2Scenario.QadFile = QADFile.FromFile(sceneryFolder + "\\V1\\" + GetSceneryName(sceneryFolder) + ".qad");
            wr2Scenario.QadFile.CellsX = width;
            wr2Scenario.QadFile.CellsY = height;
            wr2Scenario.QadFile.SetGrounds(grounds);
            SendExportStatus(string.Format("\nUpdate Scenerie: {0}x{1}\n", height, width));
            wr2Scenario.qadFile.ScenarioLength = (uint)Math.Round((decimal)(width * 14.5f), 0);
            wr2Scenario.qadFile.ScenarioWidth = (uint)Math.Round((decimal)(height * 14.5f), 0);
            wr2Scenario.VtxFile.Reset();
            wr2Scenario.QadFile.ResetPolygonData(width, height);
            wr2Scenario.QadFile.Reset();
            wr2Scenario.IdxFile.Reset();

            CreateSceneryBlocks(meshes, height, width, wr2Scenario);
            wr2Scenario.qadFile.UpdateGrounds(textureProperties);

            wr2Scenario.idxFile.Save(sceneryFolder);
            wr2Scenario.vtxFile.Save(sceneryFolder);
            wr2Scenario.qadFile.Save(sceneryFolder);

            SendExportStatus(string.Format("\nPolys: {0}", wr2Scenario.qadFile.NumberOfPolygons));
            SendExportStatus(string.Format("\nVertices: {0}", wr2Scenario.vtxFile.GetNumberOfVertices()));
            SendExportStatus(string.Format("\nTextures: {0}\n", wr2Scenario.qadFile.TextureNames.Count));
            SendExportStatus(string.Format("\nScenerie saved: {0}\n", sceneryFolder));

            return wr2Scenario;
        }

        public void Dispose()
        {
            if (this.idxFile != null)
                this.idxFile.Dispose();
            this.idxFile = null;
            if (this.vtxFile != null)
                this.vtxFile.Dispose();
            this.vtxFile = null;
            this.qadFile = null;
        }

        void IRenderableObject.Dispose()
        {
            foreach (var mesh in this.meshBlocks)
            {
                mesh.Dispose();
            }

            this.materialManager.Dispose();
        }

        void IRenderableObject.Render(int renderStep)
        {
            this.sceneManagement.ViewDistance = 100000;
            this.engine.Grafic.SetFillmodeSolid();
            this.sceneManagement.Render(renderStep);
        }

        public void Save(string sceneryFolder)
        {
            this.idxFile.Save(sceneryFolder);
            this.vtxFile.Save(sceneryFolder);
            this.qadFile.Save(sceneryFolder);
        }

        #endregion Public Methods

        #region Private Methods

        private static void CalculateBlockInfo(Mesh3dData mesh, out float blockHeight, out float xPosition, out float yPosition, out float zPosition)
        {
            float minX = float.MaxValue;
            float maxX = float.MinValue;
            float minY = float.MaxValue;
            float maxY = float.MinValue;
            float minZ = float.MaxValue;
            float maxZ = float.MinValue;

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                Vector3 position = mesh.Vertices[i].Position;
                if (position.X > maxX)
                    maxX = position.X;
                if (position.X < minX)
                    minX = position.X;
                if (position.Y > maxY)
                    maxY = position.Y;
                if (position.Y < minY)
                    minY = position.Y;
                if (position.Z > maxZ)
                    maxZ = position.Z;
                if (position.Z < minZ)
                    minZ = position.Z;
            }

            xPosition = (maxX + minX) / 2;
            yPosition = (maxY + minY) / 2;
            zPosition = (maxZ + minZ) / 2;

            // Diagonale between the most far away points.
            blockHeight = (float)Math.Sqrt((maxX - minX) * (maxX - minX) + (maxY - minY) * (maxY - minY) + (maxZ - minZ) * (maxZ - minZ)) / 2;
        }

        private static void CreateSceneryBlocks(Mesh3dData[] meshes, int height, int width, Wr2Scenario wr2Scenario)
        {
            wr2Scenario.QadFile.BlockInfos = new BlockInfo[width * height];
            for (int i = 0; i < wr2Scenario.QadFile.CellsX * wr2Scenario.QadFile.CellsY * 16; i++)
            {
                wr2Scenario.QadFile.CollisionBlocks[i] = new CollisionBlock();
            }
            SendExportStatus("\nCreating Blocks:");
            Dictionary<CompleteWr2Vertex, ushort>[,] vertexDirectory = new Dictionary<CompleteWr2Vertex, ushort>[width, height];
            for (int x = 0; x < wr2Scenario.qadFile.CellsX; x++)
            {
                for (int y = 0; y < wr2Scenario.qadFile.CellsY; y++)
                {
                    vertexDirectory[x, y] = new Dictionary<CompleteWr2Vertex, ushort>(1024);
                }
            }

            for (int y = 0; y < wr2Scenario.QadFile.CellsY; y++)
            {
                SendExportStatus("*");
                for (int x = 0; x < wr2Scenario.QadFile.CellsX; x++)
                {
                    int index = x + y * wr2Scenario.QadFile.CellsX;
                    wr2Scenario.QadFile.BlockInfos[index] = new BlockInfo(x, y);
                    Mesh3dData mesh = meshes[index];
                    BlockInfo blockInfo = wr2Scenario.QadFile.BlockInfos[index];

                    float blockHeight, xPosition, yPosition, zPosition;
                    CalculateBlockInfo(mesh, out blockHeight, out xPosition, out yPosition, out zPosition);
                    blockInfo.X = xPosition;
                    blockInfo.Y = yPosition;
                    blockInfo.Z = zPosition;
                    blockInfo.BlockY = blockHeight;
                    wr2Scenario.AddMesh(x, y, mesh, blockInfo, vertexDirectory);
                    SendExportStatus(".");
                }
            }
            SendExportStatus(".Done!");
        }

        private static Wr2Scenario FromDirectory(string sceneryFolder)
        {
            Wr2Scenario wr2Scenario = new Wr2Scenario();
            wr2Scenario.QadFile = QADFile.FromFile(sceneryFolder + "\\V1\\" + GetSceneryName(sceneryFolder) + ".qad");
            wr2Scenario.vtxFile = VTXFile.FromFile(sceneryFolder + "\\V1\\" + GetSceneryName(sceneryFolder) + ".vtx");
            wr2Scenario.idxFile = IDXFile.FromFile(sceneryFolder + "\\V1\\" + GetSceneryName(sceneryFolder) + ".idx");

            return wr2Scenario;
        }

        private static string GetSceneryName(string scenerieFolder)
        {
            // Split the Path to get the Scenery Name
            string[] temp = scenerieFolder.Split('\\');
            return (temp[temp.Length - 1]);
        }

        private static void SendExportStatus(string message)
        {
            if (exportStatus != null)
                exportStatus(message, null);
            Application.DoEvents();
        }

        /// <summary>
        /// Add a mesh to the WR2 Scenario.
        /// </summary>
        /// <param name="x">X-Position of the Scenery</param>
        /// <param name="y">Y-Position of the Scenery</param>
        /// <param name="mesh">the mesh which will added to the </param>
        /// <param name="blockInfo">the block where the infos are stored</param>
        private void AddMesh(int x, int y, Mesh3dData mesh, BlockInfo blockInfo, Dictionary<CompleteWr2Vertex, ushort>[,] vertexDictionary)
        {
            // check if the current mesh can added to the vertexblock in vtx-file.
            if (this.vtxFile.vertexBlocks[this.vtxFile.NumberOfUsedBlocks].engineVertices.Count + mesh.Vertices.Count > ushort.MaxValue)
            {
                this.vtxFile.AddNewVertexblock();
                for (int xIndex = 0; xIndex < this.qadFile.CellsX; xIndex++)
                {
                    for (int yIndex = 0; yIndex < this.qadFile.CellsY; yIndex++)
                    {
                        vertexDictionary[xIndex, yIndex].Clear();
                    }
                }
            }
            blockInfo.Chunk65K = (uint)this.vtxFile.NumberOfUsedBlocks;

            blockInfo.FirstPolygon = (uint)this.idxFile.AllIndices.Count / 3;
            blockInfo.FirstSurfaceChunk = (uint)this.qadFile.surfaceChunks.Count;

            int currentMeshPolygon = 0;

            List<IGameVertex> VerticesWr2Data = mesh.GetGamevertices("World Racing 2");
            List<MaterialItem> materials = mesh.GetMaterials("World Racing 2");
            for (int m = 0; m < materials.Count; m++)
            {
                // Add the surfacechunk
                int surfaceID = this.qadFile.GetSurfaceID((Wr2Material)materials[m].Material);
                if (mesh.PolyTextures[m] > 0)
                {
                    this.qadFile.surfaceChunks.Add(new SurfaceChunk((uint)(this.idxFile.AllIndices.Count / 3),
                            (uint)surfaceID, (uint)mesh.PolyTextures[m]));

                    blockInfo.NumberOfSurfaceChunks++;
                }

                for (int p = 0; p < mesh.PolyTextures[m]; p++)
                {
                    // add vertex to the idx-file
                    int indice = mesh.Indices[(currentMeshPolygon + p) * 3];
                    Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex1 = mesh.Vertices[indice];
                    MyOwnVertex.Wr2Data vertexWr2 = (MyOwnVertex.Wr2Data)VerticesWr2Data[indice];

                    //vertex1 = new MyOwnVertex.MyPositionNormalTextured(vertex.Position, vertex.Normal, vertexWr2.Tu, vertexWr2.Tv, vertexWr2.Tu2, vertexWr2.Tv2, vertexWr2.DiffuseColor, vertexWr2.VertexColor);
                    AddVertexToVdx(vertexDictionary, ref vertex1, ref vertexWr2);

                    indice = mesh.Indices[(currentMeshPolygon + p) * 3 + 1];
                    Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex2 = mesh.Vertices[indice];
                    vertexWr2 = (MyOwnVertex.Wr2Data)VerticesWr2Data[indice];
                    //vertex2 = new MyOwnVertex.MyPositionNormalTextured(vertex.Position, vertex.Normal, vertexWr2.Tu, vertexWr2.Tv, vertexWr2.Tu2, vertexWr2.Tv2, vertexWr2.DiffuseColor, vertexWr2.VertexColor);
                    AddVertexToVdx(vertexDictionary, ref vertex2, ref vertexWr2);

                    indice = mesh.Indices[(currentMeshPolygon + p) * 3 + 2];
                    Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex3 = mesh.Vertices[indice];
                    vertexWr2 = (MyOwnVertex.Wr2Data)VerticesWr2Data[indice];
                    // vertex = new MyOwnVertex.MyPositionNormalTextured(vertex.Position, vertex.Normal, vertexWr2.Tu, vertexWr2.Tv, vertexWr2.Tu2, vertexWr2.Tv2, vertexWr2.DiffuseColor, vertexWr2.VertexColor);
                    AddVertexToVdx(vertexDictionary, ref vertex3, ref vertexWr2);

                    blockInfo.numberOfPolygons = blockInfo.numberOfPolygons + 1;

                    AddPolygonToCollisionGroup(vertex1, vertex2, vertex3, blockInfo);
                }

                currentMeshPolygon += mesh.PolyTextures[m];
            }
        }

        private void AddPolygonToCollisionGroup(Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex1, Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex2, Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex3, BlockInfo blockInfo)
        {
            float halfScenarioWidth = this.qadFile.CellsX * 512.0f;
            float halfScenarioHeight = this.qadFile.CellsY * 512.0f;
            Vector3 offset = new Vector3(halfScenarioWidth, 0.0f, halfScenarioHeight);
            Vector3 position1 = vertex1.Position + offset;
            Vector3 position2 = vertex2.Position + offset;
            Vector3 position3 = vertex3.Position + offset;

            int BlockId = blockInfo.CellX + blockInfo.CellY * this.qadFile.CellsX;

            // Get the collisionsblocks under the polygon.
            int[] collisionBlocks = GeoMath.KrIntersect(position1,
                position2,
                position3,
                this.qadFile.CellsX * 4,
                this.qadFile.CellsY * 4);

            for (int i = 0; i < collisionBlocks.Length; i++)
            {
                this.qadFile.CollisionBlocks[collisionBlocks[i] - 1].AddData((ushort)BlockId, (ushort)(blockInfo.numberOfPolygons - 1));
            }
        }

        private void AddVertexToVdx(Dictionary<CompleteWr2Vertex, ushort>[,] vertexDictionary,
            ref Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex1, ref MyOwnVertex.Wr2Data wr2Data)
        {
            CompleteWr2Vertex completeVertex = new CompleteWr2Vertex()
            {
                vertex = vertex1,
                vertexWr2 = wr2Data
            };

            ushort indexVertex = 0;
            float indexX = ((this.qadFile.CellsX * 512.0f + vertex1.Position.X) / 1024.0f);
            float indexY = ((this.qadFile.CellsY * 512.0f + vertex1.Position.Z) / 1024.0f);
            indexX = GeoMath.EnsureRange(indexX, 0, this.qadFile.CellsX - 1);
            indexY = GeoMath.EnsureRange(indexY, 0, this.qadFile.CellsY - 1);
            if (vertexDictionary[(int)indexX, (int)indexY].TryGetValue(completeVertex, out indexVertex))
            {
                this.idxFile.AllIndices.Add(indexVertex);
            }
            else
            {
                this.vtxFile.vertexBlocks[this.vtxFile.NumberOfUsedBlocks].engineVertices.Add(vertex1);
                this.vtxFile.vertexBlocks[this.vtxFile.NumberOfUsedBlocks].wr2Data.Add(wr2Data);

                ushort indice = (ushort)(this.vtxFile.vertexBlocks[this.vtxFile.NumberOfUsedBlocks].engineVertices.Count - 1);
                this.idxFile.AllIndices.Add(indice);
                vertexDictionary[(int)indexX, (int)indexY].Add(completeVertex, indice);
            }
        }

        private void CreateMeshes(VTXFile vtxFile, QADFile qadFile, IDXFile idxFile)
        {
            this.meshes = new Mesh3dData[qadFile.CellsX * qadFile.CellsY];

            Dictionary<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured, ushort> vertexDirectory = new Dictionary<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured, ushort>();

            for (int b = 0; b < qadFile.BlockInfos.Length; b++)
            {
                BlockInfo blockInfo = qadFile.BlockInfos[b];
                VertexBlock vertexBlock = vtxFile.vertexBlocks[blockInfo.Chunk65K];

                List<ushort> indices = new List<ushort>();
                List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured> vertices = new List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured>();
                List<IGameVertex> verticesWr2Data = new List<IGameVertex>();

                vertexDirectory.Clear();
                List<int> indexedMaterilID = new List<int>();
                List<Wr2Material> materials = new List<Wr2Material>();
                List<int> numberOfUsedPolysPerMaterial = new List<int>();

                for (int s = 0; s < blockInfo.NumberOfSurfaceChunks; s++)
                {
                    int surfaceblock = s + (int)blockInfo.FirstSurfaceChunk;
                    SurfaceChunk surfaceChunk = qadFile.surfaceChunks[surfaceblock];

                    // Add the material ID.
                    indexedMaterilID.Add((int)surfaceChunk.surface);
                    materials.Add(new Wr2Material(qadFile.TextureNames[(int)qadFile.Surfaces[(int)surfaceChunk.surface].texture1ID].ToString(),
                        qadFile.TextureNames[(int)qadFile.Surfaces[(int)surfaceChunk.surface].texture2ID].ToString(),
                        qadFile.TextureNames[(int)qadFile.Surfaces[(int)surfaceChunk.surface].texture3ID].ToString(),
                        (EnumMappingMode)qadFile.Surfaces[(int)surfaceChunk.surface].mappingMode,
                        this.materialManager,
                        qadFile.Surfaces[(int)surfaceChunk.surface].mappings1,
                        qadFile.Surfaces[(int)surfaceChunk.surface].mappings2,
                        qadFile.Surfaces[(int)surfaceChunk.surface].mappings3));

                    // Seek the indices and add the vertices to the array.
                    numberOfUsedPolysPerMaterial.Add((int)surfaceChunk.numberOfPolygons);
                    for (int p = 0; p < surfaceChunk.numberOfPolygons * 3; p++)
                    {
                        int indice = (int)idxFile.AllIndices[p + (int)surfaceChunk.startPolygon * 3];

                        Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex = vertexBlock.engineVertices[indice];
                        MyOwnVertex.Wr2Data vertexWr2Data = vertexBlock.wr2Data[indice];

                        // search the vertex in the array and add the indice to the other array.
                        ushort index = 0;
                        if (vertexDirectory.TryGetValue(vertex, out index))
                        {
                            indices.Add(index);
                        }
                        else
                        {
                            indices.Add((ushort)vertices.Count);
                            vertexDirectory.Add(vertex, (ushort)vertices.Count);
                            vertices.Add(vertex);
                            verticesWr2Data.Add(vertexWr2Data);
                        }
                    }
                }

                List<Engine.Graphics.Material> engineMaterials = new List<Engine.Graphics.Material>(materials.Count);
                foreach (Wr2Material material in materials)
                {
                    engineMaterials.Add(new Engine.Graphics.Material(material));
                }

                this.meshes[b] = new Mesh3dData(indices, vertices, verticesWr2Data, numberOfUsedPolysPerMaterial, engineMaterials, this.engine.addinManager, this.engine.addinManager.CurrentAddin);
            }
            //MessageBox.Show("double vertice found: " + MyOwnVertex.MyPositionNormalTextured.doubleVerticesFound.ToString());
        }

        private void CreateRenderMeshObjects()
        {
            this.meshBlocks = new Meshobject[this.qadFile.CellsX * this.qadFile.CellsY];

            for (int mb = 0; mb < this.meshes.Length; mb++)
            {
                this.meshBlocks[mb] = new Meshobject(this.engine, this.materialManager, this.meshes[mb], this.engine.addinManager.CurrentAddin);

                this.sceneManagement.AddMeshObject(this.meshBlocks[mb]);
            }
        }

        #endregion Private Methods

        #region Private Structs

        private struct CompleteWr2Vertex
        {
            #region Public Fields

            public Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex;
            public MyOwnVertex.Wr2Data vertexWr2;

            #endregion Public Fields
        }

        #endregion Private Structs
    }
}